
'''
Created on 2009/05/24

@author: coLun
'''

import re
from random import randint

class ProblemMaker:
    @staticmethod
    def MakeCsv(map_size, color_size):
        if map_size<5 or 20<map_size or color_size<1 or 8<color_size:
            raise ValueError()
        csv = "%d,%d\r\n" % (map_size, color_size)
        for i in range(map_size):
            for j in range(map_size):
                if j!=0:
                    csv += ","
                csv += "%d" % (randint(0, color_size-1))
            csv += "\r\n"
        return csv

class Csv:
    UnsignedIntRegex = re.compile(r'^(0|[1-9][0-9]*)$')
    @staticmethod
    def ColsToUnsignedInt(val):
        if Csv.UnsignedIntRegex.search(val):
            return int(val)
        raise ValueError()
    @staticmethod
    def LineToArray(x_line):
        cols = x_line.split(',')
        result = []
        for col in cols:
            result.append(Csv.ColsToUnsignedInt(col))
        return result
    @staticmethod
    def CsvTextToCsvArray(x_csv_text):
        lines = x_csv_text.split("\r\n")
        before_line = None
        result = []
        for line in lines:
            if before_line != None:
                result.append(Csv.LineToArray(before_line))
            before_line = line
        if before_line != '' or result == []:
            raise ValueError()
        return result

class Trans:
    @staticmethod
    def CsvArrayDeserialize(x_set):
        return x_set.split('<>')
    @staticmethod
    def CsvArraySerialize(x_array):
        result = None
        for i in x_array:
            if result == None:
                result = i
            else:
                result = result + '<>' + i
        return result
    @staticmethod
    def CsvToProblem(x_csv_text):
        csv_array = Csv.CsvTextToCsvArray(x_csv_text)
        problem = Problem()
        problem.Load(csv_array)
        return problem
    @staticmethod
    def CsvToAnswer(x_csv_text):
        csv_array = Csv.CsvTextToCsvArray(x_csv_text)
        answer = Answer()
        answer.Load(csv_array)
        return answer

class Problem:
    html_color = ["#ff0000", "#00ff00", "#0000ff", "#00ffff", "#ff00ff", "#ffff00", "#ff0080", "#ff8000"]
    map = None
    map_size = None
    color_size = None
    def to_html(self):
        html = ""
        for y in range(self.map_size):
            for x in range(self.map_size):
                html += '<img src="/%d.png" />' % self.map[y][x]
            html += "<br />\n"
        return html
    def to_html2(self):
        html = ""
        for y in range(self.map_size):
            for x in range(self.map_size):
                html += '<font color="%s">#</font>' % self.html_color[self.map[y][x]]
            html += "<br>\n"
        return html
    def to_json(self):
        json = "["
        for y in range(self.map_size):
            if y!=0:
                json += ","
            json += "["
            for x in range(self.map_size):
                if x!=0:
                    json += ","
                json += str(self.map[y][x])
            json += "]"
        json += "]"
        return json
    def copy_map(self):
        cmap = []
        for line in self.map:
            cline = []
            for i in line:
                cline.append(i)
            cmap.append(cline)
        return cmap
    def Load(self, x_csv_array):
        if len(x_csv_array[0])!=2:
            raise ValueError()
        self.map_size = x_csv_array[0][0]
        self.color_size = x_csv_array[0][1]
        if self.map_size<5 or 20<self.map_size or self.color_size<1 or 8<self.color_size:
            raise ValueError()
        if len(x_csv_array) != self.map_size+1:
            raise ValueError()
        self.map = []
        for u in range(self.map_size):
            if len(x_csv_array[u+1])!=self.map_size:
                raise ValueError()
            for i in x_csv_array[u+1]:
                if self.color_size <= i:
                    raise ValueError()
            self.map.append(x_csv_array[u+1])
        return
    def clone(self):
        p = Problem()
        p.map = self.copy_map()
        p.map_size = self.map_size
        p.color_size = self.color_size
        return p
    @staticmethod
    def paint(map, x, y, c, size):
        if x<0 or y<0 or size<=x or size<=y:
            return 0
        if map[y][x]!=c:
            return 0
        map[y][x] = -1
        return 1 + Problem.paint(map, x-1, y, c, size) + Problem.paint(map, x, y-1, c, size) + Problem.paint(map, x+1, y, c, size) + Problem.paint(map, x, y+1, c, size)
    def judge(self):
        map = self.copy_map()
        point = []
        for i in range(self.color_size):
            point.append(0)
        for x in range(self.map_size):
            for  y in range(self.map_size):
                c = map[y][x]
                if 0<=c:
                    po = self.paint(map, x, y, c, self.map_size)
                    if point[c] < po:
                        point[c] = po
        k = 0
        for i in range(self.color_size):
            k += point[i]
        return k
    def rotate(self, x, y, r_size, r_count):
        if self.map_size < x+r_size or self.map_size < y+r_size or x<r_size or y<r_size:
            raise ValueError()
        xx = x * 2 - 1
        yy = y * 2 - 1
        for ix in range(r_size):
            dx = ix * 2 + 1
            for iy in range(r_size):
                dy = iy * 2 + 1
                if r_count==1:
                    dmy = self.map[(yy+dy)>>1][(xx+dx)>>1]
                    self.map[(yy+dy)>>1][(xx+dx)>>1] = self.map[(yy-dx)>>1][(xx+dy)>>1]
                    self.map[(yy-dx)>>1][(xx+dy)>>1] = self.map[(yy-dy)>>1][(xx-dx)>>1]
                    self.map[(yy-dy)>>1][(xx-dx)>>1] = self.map[(yy+dx)>>1][(xx-dy)>>1]
                    self.map[(yy+dx)>>1][(xx-dy)>>1] = dmy
                elif r_count==2:
                    dmy = self.map[(yy+dy)>>1][(xx+dx)>>1]
                    self.map[(yy+dy)>>1][(xx+dx)>>1] = self.map[(yy-dy)>>1][(xx-dx)>>1]
                    self.map[(yy-dy)>>1][(xx-dx)>>1] = dmy
                    dmy = self.map[(yy+dx)>>1][(xx-dy)>>1]
                    self.map[(yy+dx)>>1][(xx-dy)>>1] = self.map[(yy-dx)>>1][(xx+dy)>>1]
                    self.map[(yy-dx)>>1][(xx+dy)>>1] = dmy
                else:
                    dmy = self.map[(yy+dy)>>1][(xx+dx)>>1]
                    self.map[(yy+dy)>>1][(xx+dx)>>1] = self.map[(yy+dx)>>1][(xx-dy)>>1]
                    self.map[(yy+dx)>>1][(xx-dy)>>1] = self.map[(yy-dy)>>1][(xx-dx)>>1]
                    self.map[(yy-dy)>>1][(xx-dx)>>1] = self.map[(yy-dx)>>1][(xx+dy)>>1]
                    self.map[(yy-dx)>>1][(xx+dy)>>1] = dmy

class Ope:
    def action(self, x_problem):
        x_problem.rotate(self.x, self.y, self.r_size / 2, self.r_count)
        pass

class Answer:
    ope_list = None
    def Load(self, x_csv_array):
        self.ope_list = []
        for line in x_csv_array:
            if len(line)!=4:
                raise ValueError()
            o = Ope()
            o.x = line[0]
            o.y = line[1]
            o.r_size = line[2]
            o.r_count = line[3]
            if o.x==0 or o.y==0 or (o.r_size&1)==1 or o.r_count==0 or 3<o.r_count:
                raise ValueError()
            self.ope_list.append(o)
        return
    def action(self, x_problem):
        for o in self.ope_list:
            o.action(x_problem)
    def getOpeCount(self):
        return len(self.ope_list)

